#include "head.h"

int pipe_fd[2];//0读1写
void func(int num){
    write(pipe_fd[1],"123",3);

}
int main(){

    // 设置随机数种子  
    srand(time(NULL));  

    pipe(pipe_fd);
    if(fork()!=0){
        //父进程
        signal(2,func);

        wait(NULL);
        exit(0);
    }

    //子进程
    setpgid(0,0);

    //初始化结构体status
    status_t status;
    init_status(&status,4);

    MYSQL* mysql = mysql_connect();

    //启动子进程
    init_thread(&status);

    //创建三次握手socket
    int socket_fd;

    char ip[100];
    bzero(ip, sizeof(ip));
    getparameter("ip", ip);

    char port[100];
    bzero(port, sizeof(port));
    getparameter("port", port);

    init_socket(&socket_fd,port,ip);
    /* init_socket(&socket_fd,"8080","192.168.233.128"); */

    int epoll_fd=epoll_create(1);

    //添加监听对象
    add_epoll(epoll_fd,socket_fd);

    //把管道的读端放入epoll监听
    add_epoll(epoll_fd,pipe_fd[0]);

    client_t* clients = init_clients(10);
    while(1){
        struct epoll_event event[100];
        memset(event,0,sizeof(event));

        int epoll_num=epoll_wait(epoll_fd,event,100,1000);
        //printf("epoll_num: %d\n", epoll_num);

        for(int i = 0 ; i < clients->index ; i++){
            
            time_t nowtime = time(NULL);
            printf("判断时间:%d\n",(int)(nowtime - clients->desc[i].client_time));
                if((nowtime - clients->desc[i].client_time) >= 30){
                delete_epoll(epoll_fd,clients->desc[i].client_fd);
                close(clients->desc[i].client_fd);
                for(int j = i ; j < clients->index - 1 ; j++){
                    clients->desc[j] = clients->desc[j+1];
                }
                clients->index--;
                fprintf(stdout,"%d 断开连接\n",clients->desc[i].client_fd);
            }
        }


        for(int i=0;i<epoll_num;i++){
            int fd=event[i].data.fd;
            /* LOG_MSG(DEBUG,"fd?"); */
            if(fd==socket_fd){
                //有新连接进来
                int net_fd=accept(socket_fd,NULL,NULL);
                //TODO: 把net_fd放入监听

                add_epoll(epoll_fd, net_fd);
                printf("%d放入监听!\n", net_fd);

                clients->desc[clients->index].client_fd = net_fd;
                clients->desc[clients->index].client_time = time(NULL);
                clients->index++;
            }
            else if(fd==pipe_fd[0]){
                //此时说明管道可读，父进程写管道， 父进程收到信号才写管道
                // 走到: 说明父进程收到了信号

                pthread_mutex_lock(&status.lock);

                status.exit_flag=1;
                pthread_cond_broadcast(&status.cond);//此时flag=1,要求子线程退出,需要唤醒处于阻塞的子线程
                pthread_mutex_unlock(&status.lock);
                //主线程等待所以子线程退出
                for(int i=0;i<4;i++){
                    pthread_join(status.thread_id[i],NULL);
                }

                //此时所有子线程全部退出,主线程退出
                pthread_exit(NULL);
            }else{
                for(int i = 0 ; i < clients->index ; i++){
                    if(fd == clients->desc[i].client_fd){
                        clients->desc[i].client_time = time(NULL);
                       printf("登入更新时间\n");
                        break;
                    }
                }
                char token_type = '\0';
                int ret_recv = recv(fd, &token_type, sizeof(char), MSG_WAITALL);
                if(ret_recv == 0){
                    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, event);
                }
                printf("%c\n", token_type);
                if(token_type == '?'){
                    printf("work\n");
                    char cmd;
                    ret_recv = recv(fd, &cmd, sizeof(char), MSG_WAITALL);
                    if(ret_recv == 0){
                        continue;
                    }
                    printf("cmd: %c\n", cmd);
                    switch(cmd){
                    case 'l':case 'L':{
                                          sign_in(fd, mysql);
                                          break;
                                      }
                    case 'r':case 'R':{
                                          sign_up(fd, mysql);
                                          break;
                                      }
                    default:{
                                break;
                            }
                    }
                    continue;

                }else if(token_type == '!'){
                    for(int i = 0 ; i < clients->index ; i++){
                        if(fd == clients->desc[i].client_fd){
                            clients->desc[i].client_time = time(NULL);
                           printf("操作更新时间\n");
                            break;
                        }
                    }

                    off_t token_len = 0;
                    char token[1024] = {0};
                    memset(token, 0, sizeof(token));
                    ret_recv = recv(fd, &token_len, sizeof(token_len), MSG_WAITALL);
                    printf("len: %ld\n", token_len);
                    if(ret_recv == 0){

                        continue;
                    }
                    ret_recv = recv(fd, token, token_len, MSG_WAITALL);
                    if(ret_recv == 0){

                        continue;
                    }
                    printf("token: %s\n", token);

                    char user_buf[512] = {0};
                    memset(user_buf, 0, sizeof(user_buf));
                    free_JWT(token, user_buf);

                    int net_fd = atoi(strtok(user_buf, "&"));
                    /* printf("tmp_fd: %s\n", tmp_fd); */

                    printf("fd: %d\nnet_fd: %d\n", fd, net_fd);
                    char* user_id = strtok(NULL, "&");
                    /* printf("user_id: %s\n", user_id); */

                    command_t* command=(command_t*)calloc(1,sizeof(command_t));

                    //接收buf
                    off_t buf_len = 0;
                    memset(&buf_len, 0, sizeof(buf_len));
                    ret_recv = recv(fd, &buf_len, sizeof(off_t), MSG_WAITALL);
                    if(ret_recv == 0){
                        continue;
                    }

                    ret_recv = recv(fd, command->buf, buf_len, MSG_WAITALL); 
                    if(ret_recv == 0){
                        continue;
                    }
                    /* printf("buf: %s\n", command->buf); */
                    char* commd = strtok(command->buf, "&");
                    /* printf("commd: %s\n", commd); */
                    /* command->path = strtok(NULL, "&"); */
                    /* printf("path: %s\n", path); */
                    command->path = strtok(NULL, "&");

                    printf("path=%s\n",command->path);
                    char* cmds=strtok(commd," \n");
                    /* printf("cmds: %s\n", cmds); */
                    char* arg[10];
                    int arg_count=0;
                    while ((arg[arg_count] = strtok(NULL, " \n")) != NULL) {
                        /* printf("arg[%d]: %s\n", arg_count, arg[arg_count]); */
                        arg_count++;
                    }
                    //命令参数的个数
                    command->token_num=arg_count;
                    //命令  参数&路径
                    /* printf("%d: %s\n", arg_count, arg[0]); */
                    /* sleep(10); */
                    if (strcmp(cmds, "exit") == 0) {
                        printf("客户端请求退出，关闭连接\n");
                        break; // 结束当前客户端的处理，返回以关闭连接
                    }
                    if(strcmp(cmds,"cd")==0){
                        //todo,执行cd函数
                        changedir(command->path,arg[0], fd,mysql,user_id);
                    }else if(strcmp(cmds,"ls")==0){
                        //todo
                        command->types=LS;
                        lsCommand(command,fd,mysql,user_id);
                    }else if(strcmp(cmds,"rm")==0){
                        //todo
                        removefile(fd, command->path, arg[1], user_id, mysql);
                    }else if(strcmp(cmds,"pwd")==0){
                        //todo
                        command->types=PWD;
                        pwdCommand(command);
                    }
                    else if(strcmp(cmds,"mkdir") == 0){
                        // TODO : mkdir();
                        mkdirs(mysql,arg[0],command->path,fd,atoi(user_id));
                    }
                    else{
                        char error_msg[100]={0};
                        off_t len = 0;
                        //recv(net_fd, &len, sizeof(off_t), MSG_WAITALL);
                        //recv(net_fd,error_msg,len,MSG_WAITALL);
                        //LOG_MSG(INFO,error_msg);
                        //todo，打印到日志
                    }

                }else if(token_type == '#'){
                    for(int i = 0 ; i < clients->index ; i++){
                        if(fd == clients->desc[i].client_fd){
                            clients->desc[i].client_time = time(NULL);
                            break;
                        }
                    }

                    printf("puts command!\n");
                    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, event);
                    printf("删除%d 监听\n", fd);
                    pthread_mutex_lock(&status.lock);
                    //epoll_ctl(epoll_fd, EPOLL_CTL_DEL, net_fd, event);
                    enQueue(&status.queue,fd);
                    pthread_cond_broadcast(&status.cond);

                    pthread_mutex_unlock(&status.lock);



                    //todo
                }else if(token_type == '%'){
                    for(int i = 0 ; i < clients->index ; i++){
                        if(fd == clients->desc[i].client_fd){
                            clients->desc[i].client_time = time(NULL);
                            break;
                        }
                    }
                    printf("gets command!\n");
                    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, event);

                    pthread_mutex_lock(&status.lock);
                    enQueue(&status.queue,fd);
                    pthread_cond_broadcast(&status.cond);

                    pthread_mutex_unlock(&status.lock);

                    //todo

                }else{
                    for(int i = 0 ; i < clients->index ; i++){
                        if(fd == clients->desc[i].client_fd){
                            clients->desc[i].client_time = time(NULL);
                            break;
                        }
                    }
                    continue;
                }

            }
        }
    } 
    return 0;
}

